/*
 * @Author: 浅浪 11352894+shallow-wave@user.noreply.gitee.com
 * @Date: 2024-10-15 14:09:43
 * @LastEditors: 浅浪 11352894+shallow-wave@user.noreply.gitee.com
 * @LastEditTime: 2024-10-15 19:33:47
 * @FilePath: /gateway/app/app_buffer.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "app_buffer.h"
#include "log/log.h"
#include <stdlib.h>
#include <string.h>
/*初始化互斥锁*/
static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;

Buffer *app_buffer_init(int size)
{	
	if (size <= 0)
	{
		log_warn("app_buffer_init size error");	
		return NULL;
	}
	
	Buffer *buffer = malloc(sizeof(Buffer));
	if (buffer == NULL)
	{
		log_warn("app_buffer_init malloc failed");
		return NULL;
	}
	
	
	
	/*初始化buffer中的ptr ：动态分配内存*/
	buffer->ptr = malloc(size);
	
	/*如果分配失败则释放U内存并返回*/
	if (buffer->ptr == NULL)
	{
		log_warn("app_buffer_init malloc failed");
		free(buffer);
		return NULL;
	}
	
	/*初始化lock*/
	buffer->lock = init_lock;

	/*初始化其他成员*/
	buffer->len =0	;
	buffer->offset = 0;
	buffer->total_size = size;
	
	log_debug("内存分配成功");
	return buffer;
		
}


void app_buffer_free(Buffer *Buffer)
{
	/*释放buffer->ptr*/
	if (Buffer->ptr != NULL)
	{
		free(Buffer->ptr);
	}
	free(Buffer);
	log_debug("内存释放成功");
}


int app_buffer_write(Buffer *buffer, const char *data, int size)
{	
	/*加锁*/
	pthread_mutex_lock(&buffer->lock);
	/*进行参数的合法性检查*/
	if (buffer == NULL || data == NULL || size <= 0)
	{
		log_warn("app_buffer_write param error");
		return -1;
	}
	/*检查是否还有足够的空间*/
	/* 4 剩余 8
	+5	 剩余 3
	-4   剩余 8 
	*/
	//log_debug("total_size=%d,len=%d,offset=%d",buffer->total_size,buffer->len,buffer->offset);
	if (size > buffer->total_size - buffer->len)
	{
		log_warn("app_buffer_write buffer will bi full after writed");
		return -1;
	}
	
	/*写入数据*/
	/*计算写入的起始位置*/
	/* 如果write_start 大于最大值，则进行修正 
	比如 offset（起始位置） = 5 , len（已写入的数据长度） = 10 , total_size （缓冲区总长度）= 20
	5-14 10个数据已写入

	新写入的数据起始位置 = offset + len = 15 写入10个数据
	15-19 5个数据
	0-5   5个数据
	写入新数据起始位置
	*/
	int write_start = (buffer->offset + buffer->len);

	//如果write_start 超过最大值 修正write_start
	if (write_start > buffer->total_size-1)
	{
		write_start = write_start % buffer->total_size;
	}
	
	/*将数据写入buffer*/
	/*如果 新写入数据的起始位置 + 数据长度 > 缓冲区总长度 则需要分段写入*/
	if (write_start + size > buffer->total_size)
	{
		int len1 = buffer->total_size - write_start;
		memcpy(buffer->ptr + write_start, data, len1);//		log_debug("分段写入1");
		memcpy(buffer->ptr, data + len1, size - len1);//		log_debug("分段写入2");
	}else
	{
		/*一段写入即可*/
		memcpy(buffer->ptr + write_start, data, size);
	}
	
	
	/*更新len*/
	buffer->len += size;
	/*解锁*/
	pthread_mutex_unlock(&buffer->lock);
	
	//log_debug("app_buffer_write success");
	log_debug("app_buffer_write size= %d offest=%d len=%d,ptr=%s 剩余空间=%d",size,buffer->offset,buffer->len,buffer->ptr,buffer->total_size - buffer->len + buffer->offset);

	return 0;
	
}


int app_buffer_read(Buffer *buffer, char *data, int size)
{	
	
	pthread_mutex_lock(&buffer->lock);
	/*对参数进行合法性检查*/
	if (buffer == NULL || data == NULL || size <= 0)
	{
		log_warn("app_buffer_read param error");
		return -1;
	}
	/*如果len 超过 buffer中的数据长度 修正len*/
	if (size > buffer->len)
	{
		size = buffer->len;
	}
	

	
	/*读取数据*/
	/*分段读还是直接一段读*/
	/*offset 为起始位置  len 为要读取的数据长度（）*/
	if (buffer->offset + size > buffer->total_size)
	{
		/*分段读
		len1 
		*/
		int len1 = buffer->total_size - buffer->offset ;
		/*拷贝数据，从buffer的ptr（数据）中拷贝到data中，ptr的起始位置为offset，结束位置为total_size-1，长度为len1
		*/
		memcpy(data, buffer->ptr + buffer->offset, len1);
		memcpy(data + len1, buffer->ptr, size - len1);
		/*重置缓冲区偏移量*/
		buffer->offset = size - len1;
		
	}else
	{	/*将buffer的ptr（数据）中从offset开始到offset+size的数据拷贝到data中*/
		memcpy(data, buffer->ptr + buffer->offset, size);
		/*重置缓冲区偏移量*/
		buffer->offset = buffer->offset + size;
	}
	
	buffer->len -= size;
	/*解锁*/
	pthread_mutex_unlock(&buffer->lock);
	/*打印环形缓冲区信息*/
	log_debug("app_buffer_read size = %d ,offset = %d ,len=%d,ptr=%s 剩余空间 = %d",size, buffer->offset, buffer->len, buffer->ptr, buffer->total_size - buffer->len + buffer->offset);
	
	return size;
}
